package com.jcfk.eam.service.main;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.core.utils.BeanUtils;
import com.jcfk.common.security.utils.SecurityUtils;
import com.jcfk.common.web.domain.DataPage;
import com.jcfk.common.web.domain.RetResult;
import com.jcfk.eam.dao.base.EamPlanRepairOrderDao;
import com.jcfk.eam.domain.dto.base.EamPlanRepairOrderDTO;
import com.jcfk.eam.domain.dto.base.EamRepairOrderFileDTO;
import com.jcfk.eam.domain.dto.main.EamInspectionPlanPersonDTO;
import com.jcfk.eam.domain.dto.main.EamRepairOrderPartDTO;
import com.jcfk.eam.domain.dto.main.EamRepairOrderPersonDTO;
import com.jcfk.eam.domain.po.base.EamPlanRepairOrder;
import com.jcfk.eam.domain.po.base.EamRepairOrderFile;
import com.jcfk.eam.domain.po.main.EamInspectionPlanPerson;
import com.jcfk.eam.domain.po.main.EamRepairOrderPart;
import com.jcfk.eam.domain.po.main.EamRepairOrderPerson;
import com.jcfk.eam.domain.query.base.EamPlanRepairOrderQuery;
import com.jcfk.eam.domain.query.base.EamRepairPlanDetailContentQuery;
import com.jcfk.eam.domain.query.base.EamRepairPlanDetailImgQuery;
import com.jcfk.eam.service.base.EamRepairPlanDetailContentService;
import com.jcfk.eam.service.base.EamRepairPlanDetailImgService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.jcfk.common.core.utils.BeanUtils.convertList;

/**
 * 计划修工单
 *
 * @author yrl
 * {@code @date} 2024-12-10
 */
@Service
public class EamPlanRepairOrderService extends BaseService<EamPlanRepairOrderDao, EamPlanRepairOrder> {

    @Resource
    private EamRepairOrderPersonService eamRepairOrderPersonService;

    @Resource
    private EamRepairOrderFileService eamRepairOrderFileService;

    @Resource
    private EamInspectionPlanPersonService eamInspectionPlanPersonService;

    @Resource
    private EamRepairOrderService eamRepairOrderService;

    @Resource
    private EamRepairOrderPartService eamRepairOrderPartService;
    @Resource
    private EamRepairPlanDetailImgService eamRepairPlanDetailImgService;
    @Resource
    private EamRepairPlanDetailContentService eamRepairPlanDetailContentService;

    /**
     * EamPlanRepairOrder分页查询
     *
     * @param page  分页设置
     * @param query 查询条件
     * @return 分页查询结果
     */
    public DataPage<EamPlanRepairOrderDTO> queryByPage(DataPage<EamPlanRepairOrderDTO> page, EamPlanRepairOrderQuery query) {
        // 分页查询
        query.setOrderNo(StringUtils.isEmpty(query.getOrderNo()) ? query.getOrderNo() : query.getOrderNo() + "%");
        query.setAssetCode(StringUtils.isEmpty(query.getAssetCode()) ? query.getAssetCode() : query.getAssetCode() + "%");
        page = this.baseMapper.queryByPage(page, query);
        if (CollUtil.isNotEmpty(page.getRecords())) {
            List<String> orderIds = page.getRecords().stream().map(EamPlanRepairOrderDTO::getId).collect(Collectors.toList());
            List<EamRepairOrderPerson> eamRepairOrderPeople = eamRepairOrderPersonService.list(Wrappers.<EamRepairOrderPerson>lambdaQuery()
                    .in(EamRepairOrderPerson::getOrderId, orderIds));
            Map<String, List<EamRepairOrderPersonDTO>> eamRepairOrderPeopleMap = convertList(eamRepairOrderPeople, EamRepairOrderPersonDTO.class).stream()
                    .collect(Collectors.groupingBy(EamRepairOrderPersonDTO::getOrderId));
            page.getRecords().forEach(dto -> dto.setRepairOrderPersons(eamRepairOrderPeopleMap.get(dto.getId())));
        }
        return page;
    }


    /**
     * 判断EamPlanRepairOrder是已经存在
     */
    public RetResult<String> isValid(EamPlanRepairOrderDTO dto) {
        QueryWrapper<EamPlanRepairOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);

        return RetResult.ok();
    }

    /**
     * 插入计划修工单
     *
     * @param dto 插入对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(EamPlanRepairOrderDTO dto) {

        // 保存
        EamPlanRepairOrder item = new EamPlanRepairOrder();
        BeanUtils.copyProperties(dto, item);
        this.setDefaultValue(item);

        super.save(item);
    }

    /**
     * 更新计划修工单
     *
     * @param dto 更新对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(EamPlanRepairOrderDTO dto) {

        EamPlanRepairOrder byId = Assert.notNull(this.getById(dto.getId()), "未查询到工单信息");
        Assert.isTrue(byId.getOrderStatus() == 1, StrUtil.format("工单{}", byId.getOrderStatus() == 0 ? "未开始" : "已结束"));
        // 保存
        EamPlanRepairOrder item = new EamPlanRepairOrder();
        BeanUtils.copyProperties(dto, item);

        // 默认数据
        this.setDefaultValue(item);

        super.updateById(item);

        List<String> notExistUsers = new ArrayList<>();
        // 删除实际参与人信息
        eamRepairOrderPersonService.remove(Wrappers.<EamRepairOrderPerson>lambdaQuery().eq(EamRepairOrderPerson::getOrderId, item.getId()));
        if (CollUtil.isNotEmpty(dto.getRepairOrderPersons())) {
            List<EamRepairOrderPerson> repairOrderPersonList = dto.getRepairOrderPersons().stream().map(person -> {
                EamRepairOrderPerson eamInspectionPlanPerson = new EamRepairOrderPerson();
                BeanUtils.copyProperties(person, eamInspectionPlanPerson);
                eamRepairOrderPersonService.setDefaultValue(eamInspectionPlanPerson);
                eamInspectionPlanPerson.setOrderId(item.getId());
                try {
                    String userIdByEmpNo = eamRepairOrderService.getUserIdByEmpNo(person.getPersonEmpNo());
                    Assert.notEmpty(userIdByEmpNo);
                    eamInspectionPlanPerson.setUserId(userIdByEmpNo);
                } catch (RuntimeException e) {
                    notExistUsers.add(person.getPersonName());
                }
                return eamInspectionPlanPerson;
            }).collect(Collectors.toList());
            Assert.isTrue(CollUtil.isEmpty(notExistUsers), "未查询到:" + StrUtil.join(",", notExistUsers) + "人员信息");
            eamRepairOrderPersonService.saveBatch(repairOrderPersonList);
        }

        //保存使用备件
        QueryWrapper<EamRepairOrderPart> partQueryWrapper = new QueryWrapper<>();
        partQueryWrapper.lambda().eq(EamRepairOrderPart::getRepairId, dto.getId());
        eamRepairOrderPartService.remove(partQueryWrapper);
        List<EamRepairOrderPart> partList = dto.getParts().stream().map(partDTO -> {
            EamRepairOrderPart orderPart = new EamRepairOrderPart();
            orderPart.setRepairId(item.getId());
            orderPart.setSparePartId(partDTO.getSparePartId());
            orderPart.setSparePartNumber(partDTO.getSparePartNumber());
            eamRepairOrderPartService.setDefaultValue(orderPart);
            return orderPart;
        }).collect(Collectors.toList());
        if (!partList.isEmpty()) {
            eamRepairOrderPartService.saveBatch(partList);
        }

        // 删除附件历史信息
        QueryWrapper<EamRepairOrderFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EamRepairOrderFile::getRepairId, item.getId());
        queryWrapper.lambda().in(EamRepairOrderFile::getRepairFileType, ListUtil.of("1", "2"));
        eamRepairOrderFileService.remove(queryWrapper);
        // 构建附件对象
        BiFunction<List<EamRepairOrderFileDTO>, String, Stream<EamRepairOrderFile>> buildFile = (list, type) ->
                CollUtil.isEmpty(list) ? Stream.empty() : list.stream()
                        .map(image -> {
                            EamRepairOrderFile eamSopStandardImg = new EamRepairOrderFile();
                            BeanUtils.copyProperties(image, eamSopStandardImg);
                            eamRepairOrderFileService.setDefaultValue(eamSopStandardImg);
                            eamSopStandardImg.setRepairId(item.getId());
                            eamSopStandardImg.setRepairFileType(type);
                            return eamSopStandardImg;
                        });
        // 附件对象合并
        List<EamRepairOrderFile> files = Stream.concat(buildFile.apply(dto.getFixBeforeFiles(), "1"),
                        buildFile.apply(dto.getFixAfterFiles(), "2"))
                .collect(Collectors.toList());
        if (!files.isEmpty()) eamRepairOrderFileService.saveBatch(files);

    }

    /**
     * 根据批量主键删除计划修工单(逻辑删除)
     *
     * @return bool
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean logicDeleteList(EamPlanRepairOrderDTO dto) {

        EamPlanRepairOrder item = new EamPlanRepairOrder();

        this.setDefaultValue(item);
        item.setVersion(dto.getVersion());
        item.setDeleted(1);

        QueryWrapper<EamPlanRepairOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", dto.getIds());

        return this.update(item, queryWrapper);
    }

    /**
     * 设置添加默认值
     *
     * @param item 添加对象
     */
    public void setDefaultValue(EamPlanRepairOrder item) {
        if (StrUtil.isEmpty(item.getCreatedUserId())) {
            item.setCreatedUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
            item.setVersion(1L);
            item.setDeleted(0);
            item.setCreatedUserName(SecurityUtils.getUserName());
        }
        item.setLastUpdatedUserId(SecurityUtils.getUserId());
        item.setLastUpdateTime(new Date());

        item.setLastUpdatedUserName(SecurityUtils.getUserName());

    }

    /**
     * 根据主键获取计划修工单信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public EamPlanRepairOrderDTO get(String id) {
        EamPlanRepairOrderDTO eamPlanRepairOrderDTO = this.baseMapper.get(id);
        if (eamPlanRepairOrderDTO != null) {
            // 获取实际参与人
            List<EamRepairOrderPerson> eamRepairOrderPeopleList = eamRepairOrderPersonService.list(Wrappers.<EamRepairOrderPerson>lambdaQuery()
                    .eq(EamRepairOrderPerson::getOrderId, eamPlanRepairOrderDTO.getId()));
            eamPlanRepairOrderDTO.setRepairOrderPersons(convertList(eamRepairOrderPeopleList, EamRepairOrderPersonDTO.class));
            // 获取计划参与人
            List<EamInspectionPlanPerson> eamInspectionPlanPeople = eamInspectionPlanPersonService.list(Wrappers.<EamInspectionPlanPerson>lambdaQuery()
                    .eq(EamInspectionPlanPerson::getPlanId, eamPlanRepairOrderDTO.getPlanDetailId()));
            eamPlanRepairOrderDTO.setExecuteUsers(convertList(eamInspectionPlanPeople, EamInspectionPlanPersonDTO.class));

            // 获取备件
            QueryWrapper<EamRepairOrderPart> qw = new QueryWrapper<>();
            qw.lambda().eq(EamRepairOrderPart::getRepairId, id);

            // 查询数据
            List<EamRepairOrderPartDTO> parts = eamRepairOrderPartService.queryPartListByRepair(id);
            eamPlanRepairOrderDTO.setParts(parts);

            // 附件
            QueryWrapper<EamRepairOrderFile> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(EamRepairOrderFile::getRepairId, eamPlanRepairOrderDTO.getId());
            wrapper.lambda().in(EamRepairOrderFile::getRepairFileType, ListUtil.of("1", "2"));
            List<EamRepairOrderFile> fileList = eamRepairOrderFileService.list(wrapper);
            Map<String, List<EamRepairOrderFile>> repairFileTypeMap = fileList.stream().collect(Collectors.groupingBy(EamRepairOrderFile::getRepairFileType));
            // 维修前图片
            eamPlanRepairOrderDTO.setFixBeforeFiles(convertList(repairFileTypeMap.getOrDefault("1", new ArrayList<>()), EamRepairOrderFileDTO.class));
            // 维修后图片
            eamPlanRepairOrderDTO.setFixAfterFiles(convertList(repairFileTypeMap.getOrDefault("2", new ArrayList<>()), EamRepairOrderFileDTO.class));
            EamRepairPlanDetailImgQuery query = new EamRepairPlanDetailImgQuery();
            query.setRepairPlanDetailId(eamPlanRepairOrderDTO.getPlanDetailId());
            eamPlanRepairOrderDTO.setImages(eamRepairPlanDetailImgService.getList(query));
        }
        return eamPlanRepairOrderDTO;
    }


    /**
     * 根据条件获取单表信息列表
     *
     * @param query 查询条件
     * @return List<EamPlanRepairOrderDTO>
     */
    public List<EamPlanRepairOrderDTO> getList(EamPlanRepairOrderQuery query) {
        // 查询条件
        QueryWrapper<EamPlanRepairOrder> qw = new QueryWrapper<>();
        qw.eq(!StrUtil.isEmpty(query.getPlanId()), "eamPlanRepairOrder.plan_id", query.getPlanId());
        qw.eq(!StrUtil.isEmpty(query.getPlanDetailId()), "eamPlanRepairOrder.plan_detail_id", query.getPlanDetailId());
        qw.eq(!StrUtil.isEmpty(query.getExecuteTeamId()), "eamPlanRepairOrder.execute_team_id", query.getExecuteTeamId());
        qw.eq(!StrUtil.isEmpty(query.getRepairUserId()), "eamPlanRepairOrder.repair_user_id", query.getRepairUserId());
        qw.eq(query.getOrderStatus() != null, "eamPlanRepairOrder.order_status", query.getOrderStatus());
        qw.eq(query.getUserId() != null, "eamInspectionPlanPerson.user_id", query.getUserId());
        qw.in(CollUtil.isNotEmpty(query.getOrderStatuses()), "eamPlanRepairOrder.order_status", query.getOrderStatuses());
        qw.likeRight(!StrUtil.isEmpty(query.getOrderNo()), "eamPlanRepairOrder.order_no", query.getOrderNo());
        qw.likeRight(!StrUtil.isEmpty(query.getAssetCode()), "eamAssetInfo.asset_code", query.getAssetCode());
        qw.ge(!StrUtil.isEmpty(query.getPlanStartTimeStart()), "eamPlanRepairOrder.plan_start_time", query.getPlanStartTimeStart());
        qw.le(!StrUtil.isEmpty(query.getPlanStartTimeEnd()), "eamPlanRepairOrder.plan_start_time", query.getPlanStartTimeEnd());
        qw.ge(!StrUtil.isEmpty(query.getRepairStartTimeStart()), "eamPlanRepairOrder.repair_start_time", query.getRepairStartTimeStart());
        qw.le(!StrUtil.isEmpty(query.getRepairStartTimeEnd()), "eamPlanRepairOrder.repair_start_time", query.getRepairStartTimeEnd());
        qw.eq("eamPlanRepairOrder.deleted", 0);
        qw.groupBy("eamPlanRepairOrder.id,eamRepairPlanDetail.id,eamRepairPlan.id,eamAssetInfo.id,eamAssetType.id");
        // 查询数据
        return this.baseMapper.getList(qw);
    }

    /**
     * 根据主键获取计划修工单信息
     *
     * @param id 主键
     */
    public void deleteItem(String id) {
        EamPlanRepairOrder item = getById(id);
        this.setDefaultValue(item);
        item.setDeleted(1);

        this.updateById(item);
    }

    @Transactional
    public void start(EamPlanRepairOrderDTO eamPlanRepairOrder) {
        EamPlanRepairOrder byId = Assert.notNull(this.getById(eamPlanRepairOrder.getId()), "未查询到工单信息");
        Assert.isTrue(byId.getOrderStatus() == 0, StrUtil.format("工单已{}", byId.getOrderStatus() == 1 ? "开始" : "结束"));
        byId.setOrderStatus(1);
        byId.setRepairStartTime(DateUtil.date());
        String userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getUserName();
        byId.setRepairUserId(userId);
        byId.setRepairUserName(userName);
        this.updateById(byId);
    }

    @Transactional
    public void finish(EamPlanRepairOrderDTO eamPlanRepairOrder) {
        this.update(eamPlanRepairOrder);
        EamPlanRepairOrder byId = Assert.notNull(this.getById(eamPlanRepairOrder.getId()), "未查询到工单信息");
        Assert.isTrue(byId.getOrderStatus() == 1, StrUtil.format("工单{}", byId.getOrderStatus() == 0 ? "未开始" : "已结束"));
        byId.setOrderStatus(2);
        byId.setRepairEndTime(DateUtil.date());
        this.updateById(byId);

    }

    public DataPage<EamPlanRepairOrderDTO> queryMyList(DataPage<EamPlanRepairOrderDTO> page, EamPlanRepairOrderQuery query) {
        // 查询条件
        QueryWrapper<EamPlanRepairOrder> qw = new QueryWrapper<>();
        qw.eq(!StrUtil.isEmpty(query.getPlanId()), "eamPlanRepairOrder.plan_id", query.getPlanId());
        qw.eq(!StrUtil.isEmpty(query.getPlanDetailId()), "eamPlanRepairOrder.plan_detail_id", query.getPlanDetailId());
        qw.eq(!StrUtil.isEmpty(query.getExecuteTeamId()), "eamPlanRepairOrder.execute_team_id", query.getExecuteTeamId());
        qw.eq(!StrUtil.isEmpty(query.getRepairUserId()), "eamPlanRepairOrder.repair_user_id", query.getRepairUserId());
        qw.eq(query.getOrderStatus() != null, "eamPlanRepairOrder.order_status", query.getOrderStatus());
        qw.eq(query.getUserId() != null, "eamInspectionPlanPerson.user_id", query.getUserId());
        qw.in(CollUtil.isNotEmpty(query.getOrderStatuses()), "eamPlanRepairOrder.order_status", query.getOrderStatuses());
        qw.likeRight(!StrUtil.isEmpty(query.getOrderNo()), "eamPlanRepairOrder.order_no", query.getOrderNo());
        qw.likeRight(!StrUtil.isEmpty(query.getAssetCode()), "eamAssetInfo.asset_code", query.getAssetCode());
        qw.ge(!StrUtil.isEmpty(query.getPlanStartTimeStart()), "eamPlanRepairOrder.plan_start_time", query.getPlanStartTimeStart());
        qw.le(!StrUtil.isEmpty(query.getPlanStartTimeEnd()), "eamPlanRepairOrder.plan_start_time", query.getPlanStartTimeEnd());
        qw.ge(!StrUtil.isEmpty(query.getRepairStartTimeStart()), "eamPlanRepairOrder.repair_start_time", query.getRepairStartTimeStart());
        qw.le(!StrUtil.isEmpty(query.getRepairStartTimeEnd()), "eamPlanRepairOrder.repair_start_time", query.getRepairStartTimeEnd());
        qw.eq("eamPlanRepairOrder.deleted", 0);
        qw.and(!StrUtil.isEmpty(query.getSearchContent()), (e) -> e.like("eamAssetInfo.asset_code", query.getSearchContent())
                .or(t -> t.like("eamAssetInfo.asset_name", query.getSearchContent())));
        qw.orderByDesc("eamPlanRepairOrder.plan_start_time");
        qw.groupBy("eamPlanRepairOrder.id,eamRepairPlanDetail.id,eamRepairPlan.id,eamAssetInfo.id,eamAssetType.id");
        // 查询数据
        DataPage<EamPlanRepairOrderDTO> result = this.baseMapper.queryMyList(page, qw);
        for (EamPlanRepairOrderDTO eamPlanRepairOrderDTO : result.getRecords()) {
            EamRepairPlanDetailContentQuery eamRepairPlanDetailContentQuery = new EamRepairPlanDetailContentQuery();
            eamRepairPlanDetailContentQuery.setPlanDetailId(eamPlanRepairOrderDTO.getPlanDetailId());
            eamPlanRepairOrderDTO.setTypes(eamRepairPlanDetailContentService.getList(eamRepairPlanDetailContentQuery));
        }
        return result;
    }

    /**
     * 根据ID确认维修通过
     *
     * @param eamPlanRepairOrder
     */
    public void passById(EamPlanRepairOrderDTO eamPlanRepairOrder) {
        EamPlanRepairOrder planRepairOrder = new EamPlanRepairOrder();
        planRepairOrder.setId(eamPlanRepairOrder.getId());
        planRepairOrder.setOrderStatus(3);
        planRepairOrder.setLastUpdatedUserId(SecurityUtils.getUserId());
        planRepairOrder.setLastUpdateTime(new Date());
        planRepairOrder.setLastUpdatedUserName(SecurityUtils.getUserName());
        this.updateById(planRepairOrder);
    }

    /**
     * 根据ID确认维修不通过
     *
     * @param eamPlanRepairOrder
     */
    public void noPassById(EamPlanRepairOrderDTO eamPlanRepairOrder) {
        String userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getUserName();
        EamPlanRepairOrder planRepairOrder = new EamPlanRepairOrder();
        planRepairOrder.setId(eamPlanRepairOrder.getId());
        planRepairOrder.setOrderStatus(1);
        planRepairOrder.setLastUpdatedUserId(userId);
        planRepairOrder.setLastUpdateTime(new Date());
        planRepairOrder.setLastUpdatedUserName(userName);
        this.updateById(planRepairOrder);

        QueryWrapper<EamRepairOrderFile> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(EamRepairOrderFile::getRepairId, eamPlanRepairOrder.getId());
        wrapper.lambda().eq(EamRepairOrderFile::getRepairFileType, 2);
        eamRepairOrderFileService.remove(wrapper);
    }
}

